import {
    CreepLostType,
    IAllRooms,
    IConsole,
    IMapStats,
    INukesData,
    IPvpData,
    IRoomObjects,
    IUserInfo,
    Owner,
    Shard,
} from './screeps'

/**
 * 请求方法
 */
export type RequestMethods = 'GET' | 'POST'

/**
 * 封装请求
 */
export async function request<T>(
    method: RequestMethods,
    url: string,
    body: object | undefined = undefined,
    opts = {},
): Promise<T> {
    let response
    if (method === 'GET') {
        if (body) {
            url = `${url}?${Object.entries(body)
                .map(([key, value]) => `${key}=${value}`)
                .join('&')}`
        }
        response = await fetch(url, {
            method,
            ...opts,
        })
    } else if (method === 'POST') {
        response = await fetch(url, {
            method,
            body: JSON.stringify(body),
            ...opts,
        })
    }

    return response.json()
}

/**
 * 请求path
 */
export type RequestPath = `/${string}`

/**
 * 封装Screeps的api
 */
class ScreepsApi {
    /**
     * Screeps域名
     */
    public ScreepsBaseURL = 'https://screeps.com/api'

    constructor() {}

    /**
     * 获取screeps的token
     */
    public getToken() {
        return localStorage.getItem('auth').slice(1, -1) || ''
    }

    public async req<T>(method: RequestMethods, path: RequestPath, body: object | undefined = undefined): Promise<T> {
        return await request(method, `${this.ScreepsBaseURL}${path}`, body, {
            headers: {
                'Content-Type': 'application/json;charset=UTF-8',
                'X-Token': this.getToken(),
            },
        })
    }

    setScreepsBaseURL(url: string) {
        this.ScreepsBaseURL = url
    }

    /**
     * 查询地图数据
     */
    public async getMapStats(rooms: string[], shard: Shard, statName: CreepLostType | Owner) {
        return await this.req<IMapStats>('POST', '/game/map-stats', {
            rooms,
            shard,
            statName,
        })
    }

    /**
     * 提交代码到控制台
     * @param expression 代码
     */
    public async console(expression: string) {
        return await this.req<IConsole>('POST', '/user/console', {
            expression,
        })
    }

    /**
     * 获取指定用户的所有房间（包括预定房间）
     * @param id 用户id
     */
    public async getRooms(id: string) {
        return await this.req<IAllRooms>('GET', '/user/rooms', {
            id,
        })
    }

    /**
     * 获取房间对象
     * @param room 房间名
     * @param shard 分片名
     */
    public async getRoomObject(room: string, shard: Shard) {
        return await this.req<IRoomObjects>('GET', '/game/room-objects', {
            room,
            shard,
        })
    }

    /**
     * 查找指定id的用户信息
     * @param userId 用户id
     */
    public async getUserInfoByUseId(userId: string) {
        return await this.req<IUserInfo>('GET', '/user/find', {
            userId,
        })
    }

    /**
     * 查找指定用户名的用户信息
     * @param username 用户名
     */
    public async getUserInfoByUserName(username: string) {
        return await this.req<IUserInfo>('GET', '/user/find', {
            username,
        })
    }

    /**
     * 获取pvp数据
     * @param interval 时间间隔
     */
    public async getPvp(interval = 100) {
        return await this.req<IPvpData>('GET', '/experimental/pvp', {
            interval,
        })
    }

    /**
     * 获取nuker数据
     */
    public async getNukes() {
        return await this.req<INukesData>('GET', '/experimental/nukes')
    }
}

export const screepsApi = new ScreepsApi()
